package com.imchenio.springscheduleexample.instance03;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.imchenio.springscheduleexample.common.mapper.TriggerTaskDAO;
import com.imchenio.springscheduleexample.common.mapper.TriggerTaskDO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.scheduling.support.SimpleTriggerContext;

import java.util.Date;

@Slf4j
public class EnhanceCronTrigger implements Trigger {

    private final EnhanceScheduled annotation;
    private final TriggerTaskDAO triggerTaskDAO;

    private CronTrigger cronTrigger;

    private final Object object = new Object();

    public EnhanceCronTrigger(EnhanceScheduled annotation, TriggerTaskDAO triggerTaskDAO) {
        this.annotation = annotation;
        this.triggerTaskDAO = triggerTaskDAO;
    }

    @Override
    public Date nextExecutionTime(TriggerContext triggerContext) {
        TriggerTaskDO triggerTaskDO = triggerTaskDAO.selectOne(new LambdaQueryWrapper<TriggerTaskDO>()
                .eq(TriggerTaskDO::getTaskId, annotation.id())
        );
        String cron = triggerTaskDO.getCorn();
        // assert corn is valid
        if (cronTrigger == null) {
            synchronized (annotation)  {
                if (cronTrigger == null) {
                    cronTrigger = new CronTrigger(cron);
                }
            }
        }

        if (!cron.equals(cronTrigger.getExpression())) {
            synchronized (annotation) {
                if (!cron.equals(cronTrigger.getExpression())) {
                    cronTrigger = new CronTrigger(cron);
                }
            }
        }

        if (triggerContext.lastScheduledExecutionTime() != null && triggerContext.getClock().millis() < triggerContext.lastScheduledExecutionTime().getTime()) {
            if (triggerContext instanceof SimpleTriggerContext) {
                synchronized (object) {
                    if (triggerContext.lastScheduledExecutionTime() != null && triggerContext.getClock().millis() < triggerContext.lastScheduledExecutionTime().getTime()) {
                        log.debug("reload trigger context!!!");
                        ((SimpleTriggerContext) triggerContext).update(null, null, null);
                    }
                }
            }
        }
        return cronTrigger.nextExecutionTime(triggerContext);
    }
}
